﻿#region Copyright(c) 2006 ZO, All right reserved.
// -----------------------------------------------------------------------------
// Copyright(c) 2006 ZO, All right reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   1.  Redistribution of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//   2.  Redistribution in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//   3.  The name of the author may not be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
#endregion


#region Using directives

using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net.NetworkInformation;
using ZO.SmartCore.My4CSharp.Properties;
using ArgumentNullException= ZO.SmartCore.Core.ArgumentNullException;
using ZO.SmartCore.Core;

#endregion

namespace ZO.SmartCore.My4CSharp
{
    /// <summary>
    /// Provides a property, event, and methods for interacting with the network to which the computer is connected. 
    /// </summary>
    [Browsable(false)]
    [EditorBrowsable(EditorBrowsableState.Advanced)]
    public class Network : DisposableObject
    {

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="Network"/> class.
        /// </summary>
        public Network()
        {
            NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged);

            // Network
        }

        private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
        {
            if (NetworkAvailabilityChanged != null)
            {
                NetworkAvailabilityChanged(this, new NetworkAvailableEventArgs(this.IsAvailable));
            }
        } // Network
        #endregion

        #region Destructor
    

        #endregion

        #region Fields
        private byte[] _PingBuffer;

        #endregion

        #region Events
        /// <summary>
        /// Occurs when the network availability changes.
        /// </summary>
        public event EventHandler<NetworkAvailableEventArgs> NetworkAvailabilityChanged;

        #endregion

        #region Operators

        #endregion

        #region Properties
        /// <summary>Indicates whether a computer is connected to a network.</summary>
        /// <returns>Boolean.</returns>
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public bool IsAvailable
        {
            get
            {
                return NetworkInterface.GetIsNetworkAvailable();
            } // get
        } // IsAvailable

        #endregion

        #region Methods

        /// <summary>
        /// Disconnects the listener.
        /// </summary>
        [EditorBrowsableAttribute( EditorBrowsableState.Never)]
        [Browsable(false)]
        public void DisconnectListener()
        {
            NetworkChange.NetworkAddressChanged -= new NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged);
        }



        /// <summary>
        /// Override This Method To Dispose Unmanaged Resources.
        /// </summary>
        protected override void DisposeManagedResources()
        {
            this.DisconnectListener();
            base.DisposeManagedResources();
        }

        /// <summary>Pings the specified server.</summary>
        /// <returns>Boolean indicating whether or not the operation was successful.</returns>
        /// <param name="address"><see cref="T:System.Uri"></see>. The URI of the server to ping. Required.</param>
        /// <param name="timeout"><see cref="T:System.Int32"></see>. Time threshold in milliseconds for contacting the destination. Default is 500. Required. </param>
        public bool Ping(Uri address, int timeout)
        {
            if (address == null)
            {
                throw new ArgumentNullException("address");
            } // if
            return this.Ping(address.Host, timeout);
        } // Ping

        /// <summary>Pings the specified server.</summary>
        /// <returns>Boolean indicating whether or not the operation was successful.</returns>
        /// <param name="hostNameOrAddress">String. The URL, computer name, or IP number of the server to ping. Required. </param>
        [SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads")]
        public bool Ping(string hostNameOrAddress)
        {
            return this.Ping(hostNameOrAddress, 0x3e8);
        } // Ping


        /// <summary>Pings the specified server.</summary>
        /// <returns>Boolean indicating whether or not the operation was successful.</returns>
        /// <param name="address"><see cref="T:System.Uri"></see>. The URI of the server to ping. Required.</param>
        public bool Ping(Uri address)
        {
            if (address == null)
            {
                throw new ArgumentNullException("address");
            } // if
            return this.Ping(address.Host, 0x3e8);
        } // Ping

        /// <summary>Pings the specified server.</summary>
        /// <returns>Boolean indicating whether or not the operation was successful.</returns>
        /// <param name="hostNameOrAddress">String. The URL, computer name, or IP number of the server to ping. Required. </param>
        /// <param name="timeout"><see cref="T:System.Int32"></see>. Time threshold in milliseconds for contacting the destination. Default is 500. Required. </param>
        [SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads")]
        public bool Ping(string hostNameOrAddress, int timeout)
        {
            if (!this.IsAvailable)
            {
                throw new InvalidOperationException(Resources.Network_NetworkNotAvailable);
            } // if
            Ping pinger = new Ping();
            PingReply reply1 = pinger.Send(hostNameOrAddress, timeout, this.PingBuffer);
            if (reply1.Status == IPStatus.Success)
            {
                return true;
            } // if
            return false;
        } // Ping

        private byte[] PingBuffer
        {
            get
            {
                if (this._PingBuffer == null)
                {
                    this._PingBuffer = new byte[0x20];
                    int num1 = 0;
                    do
                    {
                        this._PingBuffer[num1] = Convert.ToByte(0x61 + (num1 % 0x17), CultureInfo.InvariantCulture);
                        num1++;
                    }
                    while (num1 <= 0x1f);
                } // if
                return this._PingBuffer;
            } // get
        } // PingBuffer


        #endregion
    }
}
